package richy.com.floatingball;

import android.accessibilityservice.AccessibilityService;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import java.lang.reflect.Field;

/**
 * Created by rentianxin on 17-10-16.
 */

public class FloatingBallView extends LinearLayout {
    public static final String TAG = "FloatingBallView";
    private ImageView mImgBall;//实际平常显示的
    private ImageView mImgBigBall;//变换时放大显示
    private ImageView mImgBg;//背景

    private WindowManager mWindowManager;

    private WindowManager.LayoutParams mLayoutParams;

    private long mLastDownTime;

    private float mLastDownX;
    private float mLastDownY;
    private boolean mIsLongTouch;

    private boolean mIsTouching;

    private float mTouchSlop;//判断是滑动还是点击的可移动边距

    private final static long LONG_CLICK_LIMIT = 300;
    private final static long REMOVE_LIMIT = 1500;
    private final static long CLICK_LIMIT = 200;
    private int mStatusBarHeight;

    private AccessibilityService mService;

    private int mCurrentMode;

    private final static int MODE_NONE = 0x000;

    private final static int MODE_DOWN = 0x001;
    private final static int MODE_UP = 0x002;
    private final static int MODE_LEFT = 0x003;
    private final static int MODE_RIGHT = 0x004;
    private final static int MODE_MOVE = 0x005;
    private final static int MODE_GONE = 0x006;
    private final static int OFFSET = 30;

    private float mBigBallX;

    private float mBigBallY;
    private int mOffsetToParent;

    private int mOffsetToParentY;
    private Vibrator mVibrator;
    private long[] mPattern = {0, 100};

    public FloatingBallView(FloatingBallService context) {
        super(context);
        mService = context;
        mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
        mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        initView();
    }


    private void initView() {
        inflate(getContext(), R.layout.layout_ball, this);
        mImgBall = (ImageView) findViewById(R.id.img_ball);
        mImgBigBall = (ImageView) findViewById(R.id.img_big_ball);
        mImgBg = (ImageView) findViewById(R.id.img_bg);

        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        mCurrentMode = MODE_NONE;
        mStatusBarHeight = getStatusBarHeight();
        mOffsetToParent = dp2px(25);
        mOffsetToParentY = mStatusBarHeight + mOffsetToParent;

        mImgBigBall.post(new Runnable() {
            @Override
            public void run() {
                mBigBallX = getX();//获取的是相对视图位置
                mBigBallY = getY();
            }
        });
        mImgBg.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        mIsTouching = true;
                        mLastDownTime = System.currentTimeMillis();
                        mLastDownX = event.getX();
                        mLastDownY = event.getY();
                        postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                if (isLongTouch()) {
                                    mIsLongTouch = true;
                                    mVibrator.vibrate(mPattern, -1);
                                }
                            }
                        }, LONG_CLICK_LIMIT);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (!mIsTouching && isTouchSlop(event)) {//点按是轻微移动
                            return true;
                        }
                        if (mIsLongTouch && (mCurrentMode == MODE_NONE || mCurrentMode == MODE_MOVE)) {
                            mLayoutParams.x = (int) (event.getRawX() - mOffsetToParent);//??
                            mLayoutParams.y = (int) (event.getRawY() - mOffsetToParentY);//??
                            mWindowManager.updateViewLayout(FloatingBallView.this, mLayoutParams);
                            mBigBallX = mImgBigBall.getX();//???
                            mBigBallY = mImgBigBall.getY();
                            mCurrentMode = MODE_MOVE;
                        } else {
                            //移动时改变相应模式
                            doGesture(event);
                        }
                        break;
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        mIsTouching = false;
                        if (mIsLongTouch) {
                            mIsLongTouch = false;
                        } else if (isClick(event)) {
                            AccessibilityUtils.doBack(mService);
                        } else {
                            //手指抬起后根据相应状态做改变
                            doUp();
                        }
                        mImgBall.setVisibility(VISIBLE);
                        mImgBigBall.setVisibility(GONE);
                        mCurrentMode = MODE_NONE;
                        break;
                }
                return true;
            }
        });
    }

    /**
     * 手指抬起后根据当前状态做相应的动作
     */
    private void doUp() {
        switch (mCurrentMode) {
            case MODE_LEFT:
            case MODE_RIGHT:
                AccessibilityUtils.doLeftOrRight(mService);
                break;
            case MODE_DOWN:
                AccessibilityUtils.doPullDown(mService);
                break;
            case MODE_UP:
                AccessibilityUtils.doPullUp(mService);
                break;
        }
        mImgBigBall.setX(mBigBallX);
        mImgBigBall.setY(mBigBallY);

    }

    /**
     * 移动操作(左右滑动，上下拉伸)，根据MotionEvent改变相应mCurrentMode
     *
     * @param event
     */
    private void doGesture(MotionEvent event) {
        float offsetX = event.getX() - mLastDownX;
        float offsetY = event.getY() - mLastDownY;
        if (Math.abs(offsetX) < mTouchSlop && Math.abs(offsetY) < mTouchSlop) {
            // 不足以触发移动
            return;
        }
        if (Math.abs(offsetX) > Math.abs(offsetY)) {//左右滑动
            if (offsetX > 0) {//向右
                if (mCurrentMode == MODE_RIGHT) {
                    return;
                }
                mCurrentMode = MODE_RIGHT;
                mImgBigBall.setX(mBigBallX + OFFSET);
            } else {//to left
                if (mCurrentMode == MODE_LEFT) {
                    return;
                }
                mCurrentMode = MODE_LEFT;
                mImgBigBall.setX(mBigBallX - OFFSET);
            }

        } else {//上下拉
            if (offsetY > 0) {//to down
                if (mCurrentMode == MODE_DOWN || mCurrentMode == MODE_GONE) {
                    return;
                }
                mCurrentMode = MODE_DOWN;
                mImgBigBall.setX(mBigBallX);
                mImgBigBall.setY(mBigBallY + OFFSET);
                //如果长时间保持下拉状态，将会触发移除悬浮球功能
                postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (mCurrentMode == MODE_DOWN && mIsTouching) {
                            toRemove();
                            mCurrentMode = MODE_GONE;
                        }
                    }
                }, REMOVE_LIMIT);
            } else {//to up
                if (mCurrentMode == MODE_UP) {
                    return;
                }
                mCurrentMode = MODE_UP;
                mImgBigBall.setX(mBigBallX);
                mImgBigBall.setY(mBigBallY - OFFSET);
            }
        }
    }

    /**
     * 移除悬浮球
     */
    private void toRemove() {
        mVibrator.vibrate(mPattern, -1);
        Intent intent = new Intent(getContext(), FloatingBallService.class);
        Bundle bundle = new Bundle();
        bundle.putInt(FloatingBallService.TYPE, FloatingBallService.TYPE_DEL);
        intent.putExtras(bundle);
        getContext().startService(intent);
        Toast.makeText(mService, "一直下拉移除悬浮球", Toast.LENGTH_SHORT).show();
    }

    /**
     * 判断是否是轻微移动
     *
     * @param event
     * @return
     */
    private boolean isTouchSlop(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        if (Math.abs(x - mLastDownX) < mTouchSlop && Math.abs(y - mLastDownY) < mTouchSlop) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否是点击
     *
     * @param event
     * @return
     */
    private boolean isClick(MotionEvent event) {
        if (Math.abs(event.getX() - mLastDownY) < mTouchSlop * 2 && Math.abs(event.getY() - mLastDownY) < mTouchSlop * 2 && (System.currentTimeMillis() - mLastDownTime) < CLICK_LIMIT) {
            return true;
        }
        return false;
    }

    private boolean isLongTouch() {
        long time = System.currentTimeMillis();
        if (mIsTouching && mCurrentMode == MODE_NONE && (time - mLastDownTime) >= LONG_CLICK_LIMIT) {
            Log.d(TAG, "is Long Touch");
            return true;
        }
        return false;
    }

    public void setLayoutParams(WindowManager.LayoutParams layoutParams) {
        mLayoutParams = layoutParams;
    }

    private int getStatusBarHeight() {
        int statusBarHeight = 0;
        try {
            Class c = Class.forName("com.android.internal.R$dimen");
            Object o = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = (Integer) field.get(o);
            statusBarHeight = getResources().getDimensionPixelSize(x);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusBarHeight;
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
    }
}
